package v5

import (
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/sha256"
	"fmt"
	"log"
	"math/big"
)

func (cli *CLI) createBlockChain(address string) {
	NewBlockChain(address)
	fmt.Println("create blockchain successfully!")
}

func (cli *CLI) printChain() {
	blockChain := GetBlockChain()
	if blockChain == nil {
		fmt.Println("printChain fail GetBlockChain !")
		return
	}
	defer blockChain.DB.Close()
	var it = BlockChainIterator{
		blockChain.DB,
		blockChain.TailHash,
	}
	count := 1
	for {
		block := it.Next()
		fmt.Println(" 开始---------------------------------", count)
		fmt.Printf("Version : %d\n", block.Version)
		fmt.Printf("PrevBlockHash : %x\n", block.PreHash)
		fmt.Printf("Hash : %x\n", block.Hash)
		fmt.Printf("MerkleRoot : %x\n", block.MerkleRoot)
		fmt.Printf("TimeStamp : %d\n", block.Timestamp)
		fmt.Printf("Difficuty : %d\n", block.Difficulty)
		fmt.Printf("Nonce : %d\n", block.Nonce)
		for _, transaction := range block.Transactions {
			fmt.Printf("------transaction : %x\n", transaction.TXID)
			fmt.Printf("IsCoinbase %v\n", transaction.IsCoinbase())
			for i0, output := range transaction.TxOutputs {
				fmt.Printf("output[%d].Value : %f\n", i0, output.Value)
				fmt.Printf("output[%d].PublicKeyHash : %x\n", i0, output.PublicKeyHash)
			}
			for i1, input := range transaction.TxInputs {
				fmt.Printf("input[%d].TxID : %x\n", i1, input.TxID)
				fmt.Printf("input[%d].Index : %d\n", i1, input.Index)
				fmt.Printf("input[%d].Signature : %x\n", i1, input.Signature)
				fmt.Printf("input[%d].PublicKey : %x\n", i1, input.PublicKey)
			}
		}
		fmt.Println("结束----------------------------------", count)
		count++
		if len(block.PreHash) == 0 {
			fmt.Println("打印所有区块完成!")
			break
		}
	}
}

func (cli *CLI) getBalance(address string) {
	blockChain := GetBlockChain()
	if blockChain == nil {
		fmt.Println("printChain fail GetBlockChain !")
		return
	}
	defer blockChain.DB.Close()
	balance := blockChain.GetBalance(address)
	fmt.Printf("balance of %s : %f\n", address, balance)
	fmt.Println("getBalance successfully!")
}

// 转账交易
func (cli *CLI) send(from, to, miner string, amount float64) {
	blockChain := GetBlockChain()
	if blockChain == nil {
		fmt.Println("printChain fail GetBlockChain !")
		return
	}
	defer blockChain.DB.Close()
	transaction := NewTransaction(from, to, amount, blockChain)

	coinbaseTransaction := NewCoinbaseTransaction(miner, GetRandomString(32)) //这里产生一个随机数目的是使后续计算的TXID不一样
	blockChain.AddBlock([]*Transaction{transaction, coinbaseTransaction})
	fmt.Println("send successfully!")
}

// 创建钱包
func (cli *CLI) createWallet() {
	address := NewWallets()
	fmt.Printf("createWallet [%s]\n", address)
	fmt.Println("createWallet successfully!")
}

// 获取所有已创建的钱包地址
func (cli *CLI) listAddresses() {
	list := ListAddresses()
	for k, wallet := range list.MapAddress {
		//cli.getBalance(k)
		fmt.Println("地址(如果想同时打印余额,可以调用 cli.getBalance(k)): ", k)
		fmt.Println("测试签名打开下面代码-------------")
		//生成公钥
		privateKey := wallet.PrivateKey
		pubKey := privateKey.PublicKey
		data := "hello world!"
		hash := sha256.Sum256([]byte(data))
		//签名
		r, s, err := ecdsa.Sign(rand.Reader, privateKey, hash[:])
		if err != nil {
			log.Panic()
		}
		//把r，s进行序列化传输
		signature := append(r.Bytes(), s.Bytes()...)
		//2. 拆分我们signature，平均分，前半部分给r, 后半部分给s
		//1. 定义两个辅助的big.int
		r1 := big.Int{}
		s1 := big.Int{}
		r1.SetBytes(signature[:len(signature)/2])
		s1.SetBytes(signature[len(signature)/2:])
		res := ecdsa.Verify(&pubKey, hash[:], &r1, &s1)
		fmt.Printf("签名校验结果: %v\n", res)
	}
	fmt.Println("listAddresses successfully!")
}
